<!--
  智慧社区管理系统 - 登录日志
  @author Wu.Liang
  @date 2024-01-01
  @updated 2025-07-28 - 设计美观的登录日志页面
-->
<template>
    <div class="login-log">
        <!-- 页面标题和描述 -->
        <div class="page-header">
            <div class="page-title">
                <h1>登录日志</h1>
                <p class="page-desc">记录系统用户的登录行为，包括登录时间、IP地址、设备信息等详细信息</p>
            </div>
            <div class="page-actions">
                <el-button type="primary" :icon="Download" @click="handleExport">
                    导出日志
                </el-button>
                <el-button :icon="Delete" @click="handleClear" type="danger">
                    清空日志
                </el-button>
            </div>
        </div>

        <!-- 搜索和筛选区域 -->
        <el-card class="search-card" shadow="never">
            <el-form :model="searchForm" inline class="search-form">
                <el-form-item label="用户名">
                    <el-input 
                        v-model="searchForm.username" 
                        placeholder="请输入用户名"
                        clearable
                        style="width: 150px"
                    />
                </el-form-item>
                
                <el-form-item label="登录状态">
                    <el-select 
                        v-model="searchForm.status" 
                        placeholder="请选择状态"
                        clearable
                        style="width: 120px"
                    >
                        <el-option label="成功" :value="1" />
                        <el-option label="失败" :value="0" />
                    </el-select>
                </el-form-item>
                
                <el-form-item label="IP地址">
                    <el-input 
                        v-model="searchForm.ipAddress" 
                        placeholder="请输入IP地址"
                        clearable
                        style="width: 150px"
                    />
                </el-form-item>
                
                <el-form-item label="登录时间">
                    <el-date-picker
                        v-model="searchForm.timeRange"
                        type="datetimerange"
                        range-separator="至"
                        start-placeholder="开始时间"
                        end-placeholder="结束时间"
                        format="YYYY-MM-DD HH:mm:ss"
                        value-format="YYYY-MM-DD HH:mm:ss"
                        style="width: 320px"
                    />
                </el-form-item>
                
                <el-form-item>
                    <el-button type="primary" :icon="Search" @click="handleSearch">
                        搜索
                    </el-button>
                    <el-button :icon="Refresh" @click="handleReset">
                        重置
                    </el-button>
                </el-form-item>
            </el-form>
        </el-card>

        <!-- 统计信息卡片 -->
        <el-row :gutter="20" class="stats-row">
            <el-col :span="6">
                <el-card class="stats-card" shadow="hover">
                    <div class="stats-content">
                        <div class="stats-icon success">
                            <el-icon><User /></el-icon>
                        </div>
                        <div class="stats-info">
                            <div class="stats-number">{{ stats.totalLogins }}</div>
                            <div class="stats-label">总登录次数</div>
                        </div>
                    </div>
                </el-card>
            </el-col>
            
            <el-col :span="6">
                <el-card class="stats-card" shadow="hover">
                    <div class="stats-content">
                        <div class="stats-icon success">
                            <el-icon><Check /></el-icon>
                        </div>
                        <div class="stats-info">
                            <div class="stats-number">{{ stats.successLogins }}</div>
                            <div class="stats-label">成功登录</div>
                        </div>
                    </div>
                </el-card>
            </el-col>
            
            <el-col :span="6">
                <el-card class="stats-card" shadow="hover">
                    <div class="stats-content">
                        <div class="stats-icon danger">
                            <el-icon><Close /></el-icon>
                        </div>
                        <div class="stats-info">
                            <div class="stats-number">{{ stats.failedLogins }}</div>
                            <div class="stats-label">失败登录</div>
                        </div>
                    </div>
                </el-card>
            </el-col>
            
            <el-col :span="6">
                <el-card class="stats-card" shadow="hover">
                    <div class="stats-content">
                        <div class="stats-icon warning">
                            <el-icon><Clock /></el-icon>
                        </div>
                        <div class="stats-info">
                            <div class="stats-number">{{ stats.todayLogins }}</div>
                            <div class="stats-label">今日登录</div>
                        </div>
                    </div>
                </el-card>
            </el-col>
        </el-row>

        <!-- 日志列表区域 -->
        <el-card class="log-card" shadow="never">
            <template #header>
                <div class="card-header">
                    <span class="card-title">登录日志列表</span>
                    <div class="card-actions">
                        <el-tag type="info" size="small">
                            共 {{ total }} 条记录
                        </el-tag>
                    </div>
                </div>
            </template>
            
            <el-table 
                :data="logList" 
                border 
                stripe
                v-loading="loading"
                style="width: 100%"
            >
                <el-table-column prop="id" label="ID" width="80" align="center" />
                
                <el-table-column prop="username" label="用户名" width="120" />
                
                <el-table-column prop="realName" label="真实姓名" width="120" />
                
                <el-table-column prop="ipAddress" label="IP地址" width="130" />
                
                <el-table-column prop="location" label="登录地点" width="150" />
                
                <el-table-column prop="deviceInfo" label="设备信息" min-width="200" show-overflow-tooltip />
                
                <el-table-column prop="browser" label="浏览器" width="120" />
                
                <el-table-column prop="os" label="操作系统" width="120" />
                
                <el-table-column prop="status" label="状态" width="80" align="center">
                    <template #default="{ row }">
                        <el-tag 
                            :type="row.status === 1 ? 'success' : 'danger'"
                            size="small"
                        >
                            {{ row.status === 1 ? '成功' : '失败' }}
                        </el-tag>
                    </template>
                </el-table-column>
                
                <el-table-column prop="loginTime" label="登录时间" width="180" align="center" />
                
                <el-table-column prop="logoutTime" label="登出时间" width="180" align="center">
                    <template #default="{ row }">
                        {{ row.logoutTime || '-' }}
                    </template>
                </el-table-column>
                
                <el-table-column prop="duration" label="在线时长" width="120" align="center">
                    <template #default="{ row }">
                        {{ row.duration || '-' }}
                    </template>
                </el-table-column>
                
                <el-table-column label="操作" width="120" align="center" fixed="right">
                    <template #default="{ row }">
                        <el-button 
                            type="primary" 
                            size="small" 
                            :icon="View"
                            @click="handleView(row)"
                        >
                            详情
                        </el-button>
                    </template>
                </el-table-column>
            </el-table>
            
            <!-- 分页 -->
            <div class="pagination-wrapper">
                <el-pagination
                    v-model:current-page="pagination.current"
                    v-model:page-size="pagination.size"
                    :page-sizes="[10, 20, 50, 100]"
                    :total="total"
                    layout="total, sizes, prev, pager, next, jumper"
                    @size-change="handleSizeChange"
                    @current-change="handleCurrentChange"
                />
            </div>
        </el-card>

        <!-- 日志详情弹窗 -->
        <el-dialog
            v-model="detailVisible"
            title="登录日志详情"
            width="800px"
            :close-on-click-modal="false"
        >
            <div v-if="currentLog" class="log-detail">
                <el-descriptions :column="2" border>
                    <el-descriptions-item label="日志ID">
                        {{ currentLog.id }}
                    </el-descriptions-item>
                    <el-descriptions-item label="用户名">
                        {{ currentLog.username }}
                    </el-descriptions-item>
                    <el-descriptions-item label="真实姓名">
                        {{ currentLog.realName }}
                    </el-descriptions-item>
                    <el-descriptions-item label="IP地址">
                        {{ currentLog.ipAddress }}
                    </el-descriptions-item>
                    <el-descriptions-item label="登录地点">
                        {{ currentLog.location }}
                    </el-descriptions-item>
                    <el-descriptions-item label="登录状态">
                        <el-tag :type="currentLog.status === 1 ? 'success' : 'danger'">
                            {{ currentLog.status === 1 ? '成功' : '失败' }}
                        </el-tag>
                    </el-descriptions-item>
                    <el-descriptions-item label="登录时间">
                        {{ currentLog.loginTime }}
                    </el-descriptions-item>
                    <el-descriptions-item label="登出时间">
                        {{ currentLog.logoutTime || '-' }}
                    </el-descriptions-item>
                    <el-descriptions-item label="在线时长">
                        {{ currentLog.duration || '-' }}
                    </el-descriptions-item>
                    <el-descriptions-item label="浏览器">
                        {{ currentLog.browser }}
                    </el-descriptions-item>
                    <el-descriptions-item label="操作系统">
                        {{ currentLog.os }}
                    </el-descriptions-item>
                    <el-descriptions-item label="设备信息">
                        {{ currentLog.deviceInfo }}
                    </el-descriptions-item>
                    <el-descriptions-item label="用户代理">
                        {{ currentLog.userAgent }}
                    </el-descriptions-item>
                </el-descriptions>
                
                <div v-if="currentLog.failReason" class="detail-section">
                    <h4>失败原因</h4>
                    <el-input
                        v-model="currentLog.failReason"
                        type="textarea"
                        :rows="3"
                        readonly
                        class="error-message"
                    />
                </div>
                
                <div class="detail-section">
                    <h4>会话信息</h4>
                    <el-input
                        v-model="currentLog.sessionInfo"
                        type="textarea"
                        :rows="4"
                        readonly
                        placeholder="无会话信息"
                    />
                </div>
            </div>
            
            <template #footer>
                <el-button @click="detailVisible = false">关闭</el-button>
            </template>
        </el-dialog>
    </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { 
    Search, 
    Refresh, 
    Download, 
    Delete, 
    View,
    User,
    Check,
    Close,
    Clock
} from '@element-plus/icons-vue'
import { getLoginLogList, exportLoginLog, clearLoginLog, type LoginLogQueryParams, type LoginLog } from '@/api/user'

// 搜索表单
const searchForm = reactive({
    username: '',
    status: undefined as number | undefined,
    ipAddress: '',
    timeRange: [] as string[]
})

// 分页配置
const pagination = reactive({
    current: 1,
    size: 20
})

// 数据状态
const loading = ref(false)
const total = ref(0)
const logList = ref<any[]>([])
const detailVisible = ref(false)
const currentLog = ref<any>(null)

// 统计信息
const stats = reactive({
    totalLogins: 1250,
    successLogins: 1180,
    failedLogins: 70,
    todayLogins: 45
})



// 搜索
const handleSearch = () => {
    pagination.current = 1
    fetchLogList()
}

// 重置
const handleReset = () => {
    Object.assign(searchForm, {
        username: '',
        status: undefined,
        ipAddress: '',
        timeRange: []
    })
    pagination.current = 1
    fetchLogList()
}

// 导出日志
const handleExport = async () => {
    try {
        // 构建查询参数
        const params: LoginLogQueryParams = {
            current: 1,
            size: 10000, // 导出所有数据
            username: searchForm.username || undefined,
            loginStatus: searchForm.status || undefined,
            loginIp: searchForm.ipAddress || undefined,
            startTime: searchForm.timeRange?.[0] || undefined,
            endTime: searchForm.timeRange?.[1] || undefined
        }
        
        const response = await exportLoginLog(params)
        ElMessage.success(response.data || '导出成功')
    } catch (error: any) {
        console.error('导出失败:', error)
        ElMessage.error('导出失败：' + (error.message || '未知错误'))
    }
}

// 清空日志
const handleClear = async () => {
    try {
        await ElMessageBox.confirm('确定要清空所有登录日志吗？此操作不可恢复！', '警告', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
        })
        
        await clearLoginLog()
        ElMessage.success('清空成功')
        fetchLogList() // 刷新列表
    } catch (error: any) {
        if (error !== 'cancel') {
            console.error('清空失败:', error)
            ElMessage.error('清空失败：' + (error.message || '未知错误'))
        }
    }
}

// 查看详情
const handleView = (row: any) => {
    currentLog.value = row
    detailVisible.value = true
}

// 分页大小改变
const handleSizeChange = (size: number) => {
    pagination.size = size
    pagination.current = 1
    fetchLogList()
}

// 当前页改变
const handleCurrentChange = (current: number) => {
    pagination.current = current
    fetchLogList()
}

// 获取日志列表
const fetchLogList = async () => {
    loading.value = true
    
    try {
        // 构建查询参数
        const params: LoginLogQueryParams = {
            current: pagination.current,
            size: pagination.size,
            username: searchForm.username || undefined,
            loginStatus: searchForm.status || undefined,
            loginIp: searchForm.ipAddress || undefined,
            startTime: searchForm.timeRange?.[0] || undefined,
            endTime: searchForm.timeRange?.[1] || undefined
        }
        
        // 调用后端API获取登录日志列表
        const response = await getLoginLogList(params)
        
        if (response.data) {
            // 转换为登录日志格式
            logList.value = response.data.records.map((log: LoginLog) => ({
                id: log.id,
                username: log.username || '',
                realName: '', // 需要从用户信息中获取
                ipAddress: log.loginIp || '',
                location: log.loginAddress || '',
                deviceInfo: '', // 需要解析userAgent
                browser: log.browser || '',
                os: log.os || '',
                status: log.loginStatus || 1,
                loginTime: log.loginTime || '',
                logoutTime: log.logoutTime || '',
                duration: log.onlineDuration ? `${Math.floor(log.onlineDuration / 3600)}小时${Math.floor((log.onlineDuration % 3600) / 60)}分钟` : '',
                userAgent: '', // 需要从系统日志中获取
                sessionInfo: '', // 需要从系统日志中获取
                failReason: log.loginMessage || ''
            }))
            total.value = response.data.total
            
            // 如果没有数据，显示提示信息
            if (response.data.total === 0) {
                ElMessage.info('暂无登录日志数据')
            }
        }
        
    } catch (error: any) {
        console.error('获取登录日志失败:', error)
        
        // 根据错误类型显示不同的提示信息
        if (error.response) {
            const { status, data } = error.response
            switch (status) {
                case 401:
                    // 优先使用后端返回的错误消息，如果没有则使用默认消息
                    ElMessage.error(data?.message || data?.msg || '登录已过期，请重新登录')
                    break
                case 403:
                    ElMessage.error('无权限访问登录日志')
                    break
                case 404:
                    ElMessage.error('登录日志接口不存在')
                    break
                case 500:
                    ElMessage.error('服务器内部错误，请联系管理员')
                    break
                default:
                    ElMessage.error(data?.message || '获取登录日志失败')
            }
        } else if (error.request) {
            ElMessage.error('网络连接失败，请检查网络设置')
        } else {
            ElMessage.error('获取登录日志失败：' + (error.message || '未知错误'))
        }
        
        // 清空数据
        logList.value = []
        total.value = 0
    } finally {
        loading.value = false
    }
}

// 页面加载时获取数据
onMounted(() => {
    fetchLogList()
})
</script>

<style scoped>
.login-log {
    padding: 20px;
    background-color: #f5f7fa;
    min-height: calc(100vh - 120px);
}

.page-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    margin-bottom: 20px;
    padding: 20px;
    background: white;
    border-radius: 8px;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}

.page-title h1 {
    margin: 0 0 8px 0;
    font-size: 24px;
    font-weight: 600;
    color: #303133;
}

.page-desc {
    margin: 0;
    color: #606266;
    font-size: 14px;
}

.page-actions {
    display: flex;
    gap: 12px;
}

.search-card {
    margin-bottom: 20px;
}

.search-form {
    margin: 0;
}

.stats-row {
    margin-bottom: 20px;
}

.stats-card {
    border: 1px solid #e4e7ed;
    transition: all 0.3s ease;
}

.stats-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
}

.stats-content {
    display: flex;
    align-items: center;
    padding: 10px 0;
}

.stats-icon {
    width: 60px;
    height: 60px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-right: 16px;
    font-size: 24px;
    color: white;
}

.stats-icon.success {
    background: linear-gradient(135deg, #67c23a, #85ce61);
}

.stats-icon.danger {
    background: linear-gradient(135deg, #f56c6c, #f78989);
}

.stats-icon.warning {
    background: linear-gradient(135deg, #e6a23c, #ebb563);
}

.stats-info {
    flex: 1;
}

.stats-number {
    font-size: 28px;
    font-weight: 700;
    color: #303133;
    line-height: 1;
    margin-bottom: 4px;
}

.stats-label {
    font-size: 14px;
    color: #606266;
}

.log-card {
    margin-bottom: 20px;
}

.card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.card-title {
    font-size: 16px;
    font-weight: 600;
    color: #303133;
}

.card-actions {
    display: flex;
    gap: 12px;
}

.pagination-wrapper {
    display: flex;
    justify-content: center;
    margin-top: 20px;
    padding-top: 20px;
    border-top: 1px solid #f0f0f0;
}

.log-detail {
    padding: 20px 0;
}

.detail-section {
    margin-top: 20px;
}

.detail-section h4 {
    margin: 0 0 12px 0;
    font-size: 14px;
    font-weight: 600;
    color: #303133;
}

.error-message :deep(.el-textarea__inner) {
    color: #f56c6c;
    background-color: #fef0f0;
}

:deep(.el-table .el-table__cell) {
    padding: 8px 0;
}

:deep(.el-descriptions__label) {
    font-weight: 500;
    color: #303133;
}
</style> 